package com.sxl.config;

import com.sxl.domain.model.DynamicThreadPoolService;
import com.sxl.domain.model.IDynamicThreadPoolService;
import com.sxl.domain.model.entity.ThreadPoolConfigEntity;
import com.sxl.domain.model.valobj.RegistryEnumVO;
import com.sxl.listener.ThreadPoolConfigAdjustListener;
import com.sxl.registry.IRegistry;
import com.sxl.registry.redis.RedisRegistry;
import com.sxl.trigger.job.ThreadPoolDataReportJob;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author : sxl
 * @date : 2024/8/12 11:51
 * @description : 自动配置类
 */
@Slf4j
@Configuration
@EnableConfigurationProperties(DynamicThreadPoolAutoProperties.class)
public class DynamicThreadPoolAutoConfig {
    private final Logger logger = LoggerFactory.getLogger(DynamicThreadPoolAutoConfig.class);
    //应用名称，用于标识当前应用
    String applicationName;
    //redis注册器
    @Bean
    public IRegistry redisRegistry(RedissonClient redissonClient) {
        return new RedisRegistry(redissonClient);
    }
    //给定时任务配置
    @Bean
    public ThreadPoolDataReportJob threadPoolDataReportJob(IDynamicThreadPoolService dynamicThreadPoolService, IRegistry registry) {
        return new ThreadPoolDataReportJob(dynamicThreadPoolService, registry);
    }
    //动态线程池服务，获取线程池，配置本地缓存线程
    @Bean("dynamicThreadPoolService")
    public DynamicThreadPoolService dynamicThreadPoolService(ApplicationContext applicationContext, Map<String, ThreadPoolExecutor> threadPoolExecutorMap,RedissonClient redissonClient){
        Logger logger = LoggerFactory.getLogger(DynamicThreadPoolAutoConfig.class);
        applicationName = applicationContext.getEnvironment().getProperty("spring.application.name");
        if(StringUtil.isBlank(applicationName)){
            logger.warn("应用程序为空，请检查配置文件");
        }
        //防止重启导致的线程池重新被初始化，导致之前的配置丢失
        //获取缓存数据设置本地配置
        Set<String> threadPoolKeys = threadPoolExecutorMap.keySet();
        for (String threadPoolKey : threadPoolKeys) {
            ThreadPoolConfigEntity threadPoolConfigEntity = redissonClient.<ThreadPoolConfigEntity>getBucket(RegistryEnumVO.THREAD_POOL_CONFIG_PARAMETER_LIST_KEY.getKey() + "_" + applicationName + "_" + threadPoolKey).get();
            if(null==threadPoolConfigEntity)
                continue;
            //根据名称获取线程池
            ThreadPoolExecutor threadPoolExecutor = threadPoolExecutorMap.get(threadPoolKey);
            threadPoolExecutor.setCorePoolSize(threadPoolConfigEntity.getCorePoolSize());
            threadPoolExecutor.setMaximumPoolSize(threadPoolConfigEntity.getMaximumPoolSize());
        }
        return new DynamicThreadPoolService(applicationName,threadPoolExecutorMap);
    }
    @Bean
    public ThreadPoolConfigAdjustListener threadPoolConfigAdjustListener(IDynamicThreadPoolService dynamicThreadPoolService, IRegistry registry) {
        return new ThreadPoolConfigAdjustListener(dynamicThreadPoolService, registry);
    }
    //监听配置
    @Bean(name = "dynamicThreadPoolRedisTopic")
    public RTopic threadPoolConfigAdjustListener(ThreadPoolConfigAdjustListener threadPoolConfigAdjustListener,RedissonClient redissonClient)   {
        //根据应用名称初始化Redisson主题
        RTopic topic = redissonClient.getTopic(RegistryEnumVO.DYNAMIC_THREAD_POOL_REDIS_TOPIC.getKey() + "_" + applicationName);
        //为动态线程池配置调整监听器注册监听事件，当有新的配置信息时(ThreadPoolConfigEntity发生更新)，触发监听器,ThreadPoolConfigAdjustListener类里的onMessage方法会执行
        topic.addListener(ThreadPoolConfigEntity.class,threadPoolConfigAdjustListener);
        return topic;
    }

}
